package modelo;

import java.util.concurrent.Semaphore;

public class Mundo {
	public static final Semaphore SEM_INTERSECCION = new Semaphore(3);
	private static Mundo instance;
	private Mapa<Bloque> mapa;
	private AdmSemaforos admSem;
	
	private Mundo(){
		this.mapa = new Mapa<Bloque>(22, 12);
		this.admSem = new AdmSemaforos(3);
		this.generarMundo();
	}
	
	public static Mundo getInstance(){
		if(instance == null){
			instance = new Mundo();
		}
		return instance;
	}
	
	public Bloque getBloqueLimitrofe(Bloque bloque, Direccion dir) {
		Integer x = bloque.getPosicion().getX();
		Integer y = bloque.getPosicion().getY();
		switch (dir) {
		case NORTE:
			y--;
			break;
		case SUR:
			y++;
			break;
		case OESTE:
			x--;
			break;
		case ESTE:
			x++;
			break;
		}	
		return this.mapa.get(x, y);
	}
	
	public void generarAuto(Direccion dir) {
		Auto auto = new Auto();
		Direccion direccion;
		Bloque destino;
		switch (dir) {
		case SUR:
			direccion = Direccion.NORTE;
			destino = this.mapa.get(11, 11);
			break;
		case ESTE:
			direccion = Direccion.OESTE;
			destino = this.mapa.get(21, 0);
			break;
		case OESTE:
			direccion = Direccion.ESTE;
			destino = this.mapa.get(0, 1);
			break;
		default:
			return;
		}
		auto.setDireccion(direccion);
		destino.entrar(auto);
		auto.start();
	}
	
	public void generarMundo(){
		for (int i = 0; i < 10; i++) {
			this.mapa.agregar(i, 0, new Calle(Direccion.OESTE, new Coordenada(i, 0)));
			this.mapa.agregar(i, 1, new Calle(Direccion.ESTE, new Coordenada(i, 1)));
			this.mapa.agregar(i + 12, 0, new Calle(Direccion.OESTE, new Coordenada(i + 12, 0)));
			this.mapa.agregar(i + 12, 1, new Calle(Direccion.ESTE, new Coordenada(i + 12, 1)));
			
			this.mapa.agregar(10, i + 2, new Calle(Direccion.SUR, new Coordenada(10, i + 2)));
			this.mapa.agregar(11, i + 2, new Calle(Direccion.NORTE, new Coordenada(11, i + 2)));
		}
		//Agrego el unico bloque de los 4 bloques criticos que tiene una unica direccion
		Calle calle = new Calle(Direccion.OESTE, new Coordenada(11, 0));
		calle.setInterseccion(true);
		this.mapa.agregar(11, 0, calle);
		//Agrego los 3 bloques con doble direccion
		this.mapa.agregar(10, 0, new CalleDobleDireccion(Direccion.OESTE, Direccion.SUR, new Coordenada(10, 0)));
		this.mapa.agregar(10, 1, new CalleDobleDireccion(Direccion.SUR, Direccion.ESTE, new Coordenada(10, 1)));
		this.mapa.agregar(11, 1, new CalleDobleDireccion(Direccion.ESTE, Direccion.NORTE, new Coordenada(11, 1)));
		
		this.mapa.agregar(9, 1, new CalleConSemaforo(Direccion.ESTE, new Coordenada(9, 1), this.getAdmSem().getSemaforo(0)));
		this.mapa.agregar(11, 2, new CalleConSemaforo(Direccion.NORTE, new Coordenada(11, 2), this.getAdmSem().getSemaforo(1)));
		this.mapa.agregar(12, 0, new CalleConSemaforo(Direccion.OESTE, new Coordenada(12, 0), this.getAdmSem().getSemaforo(2)));
	}

	public Mapa<Bloque> getMapa() {
		return mapa;
	}

	public void setMapa(Mapa<Bloque> mapa) {
		this.mapa = mapa;
	}

	public AdmSemaforos getAdmSem() {
		return admSem;
	}

	public void setAdmSem(AdmSemaforos admSem) {
		this.admSem = admSem;
	}
}
